package com.aos.iot.protocol.hll.handler;

import cn.hutool.core.util.StrUtil;
import com.aos.iot.protocol.hll.client.HllClient;
import com.aos.iot.protocol.hll.constant.HllProp;
import com.aos.iot.socket.common.ack.AckManager;
import com.aos.iot.socket.common.client.ClientBoxFactor;
import com.aos.iot.socket.common.client.IClientBox;
import com.aos.iot.socket.common.handler.AbstractHandler;
import com.aos.iot.socket.common.protocol.ProtocolFactor;
import com.aos.iot.socket.common.scheduler.CancelableScheduler;
import com.aos.iot.socket.common.store.StoreFactory;
import com.aos.iot.protocol.hll.message.HllMessage;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import static com.aos.iot.protocol.hll.constant.HllConstant.PROTOCOL_NAME;

@Slf4j
@Component
@ChannelHandler.Sharable
public class HllHandler extends AbstractHandler<HllMessage, HllClient> {


    public HllHandler(AckManager ackManager, StoreFactory<HllMessage> storeFactory, CancelableScheduler cancelableScheduler, ProtocolFactor protocolFactor, ClientBoxFactor clientBoxFactor) {
        super(ackManager, storeFactory, cancelableScheduler, protocolFactor.getProtocol(PROTOCOL_NAME), clientBoxFactor);
    }

    @Override
    protected HllClient createClient(ChannelHandlerContext ctx) {
        return new HllClient(ctx, protocol, storeFactory, ackManager, clientBoxFactor);
    }

    @Override
    protected void registerClient(IClientBox<HllMessage, HllClient> clientBox, HllClient client, HllMessage message) {
        String clientId = message.getData().getStr(HllProp.PILE_NO.getValue());
        if(StrUtil.isNotBlank(clientId)) {
            client.setClientId(clientId);
            clientBox.add(clientId, client, message.getSender());
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HllMessage message) {
        String clientId = message.getData().getStr(HllProp.PILE_NO.getValue());
        String cmd = message.getCmd();
        long startTime = System.currentTimeMillis();
        try {
            super.channelRead0(ctx, message);
        } catch (Exception e) {
            log.error("[{}:{}] happen exception message: {}", clientId, cmd, message.getContext());
            log.error(clientId, e);
        } finally {
            long endTime = System.currentTimeMillis();
            if(StrUtil.equalsIgnoreCase(clientId, "0100000001"))
                log.info("[{}:{}] 执行时长: {} 毫秒;", clientId, cmd, endTime - startTime);
        }
    }
}
